The major stages in the life cycle of software development are the design phase, the coding phase, the code complete phase, the alpha phase, the beta phase, and finally, release to market. During the design phase, the customer problems the software product will address and the functionality of the software product is defined. Typically, the completion of the functional specification marks the end of the design phase. The coding phase may already have begun. The code complete phase is reached when the code has been written but is not necessarily debugged. The alpha phase marks the point in time when the product is stable; that is, most of the major bugs have been found. In the beta phase, the product is ideally free of all major bugs; the only bugs remaining should be essentially harmless. When the product passes a final quality assurance checklist, it is ready for release to market.
As no one wants software that does not work, testing is an important part of the life cycle and can span several phases. Software testing involves devising a test case (or, more likely, a set of test cases), running the software with the test case as input, and checking that the performance of the software with the test case as input yields the expected results. Software testing can be conducted manually by humans or programmatically, referred to as automated software testing. Ideally, testing of the software should begin as soon as possible in the life cycle of the software. Generally, however, the software cannot be tested at all until the design phase has been completed, because until the design phase is complete, expected results cannot be determined. Typically, during the coding phase, the developer manually tests his code as he writes it. Automated software testing usually cannot begin until far later in the development process.
Sometimes, the only testing that is conducted is done by the developer who manually tests as he codes. A developer who tests his own work, however, is likely to overlook bugs that someone not so emotionally invested in the code will find. Furthermore, the scope of the developer's testing is typically limited to the functionality of his code and integration of his code with a limited number of other software applications.
To address these shortcomings, many software development houses have a separate software testing group that also tests the software, often using at least partially-automated testing techniques. Typically, the testing group tests complex interactions across features and across applications by writing and running test cases. It is generally agreed that involving the testing group early in the product life cycle, even as early as the design phase, reaps many benefits, including identification of inconsistencies in the functional specification, identification of hard-to-test areas and others. In general, however, the effort required to keep each test case current in the face of continued changes in feature definition, implementation and user interface (UI) tuning renders this approach impractical. Hence, writing and running test cases is typically a hurried matter that occurs at the tail end of product development. Testing and in particular, automated testing, thus tends to be perpetually behind the curve. It would be helpful if there were a way to write test cases and employ automated testing as soon as possible in the life cycle of a software product, ideally during the design phase.
Development of a suite of test cases is a challenge whenever it occurs. To test a specific feature of an application, numerous sets of tests must be written. For example, an application may permit many modes of interaction with a feature: via a mouse, keyboard, digitizer, accessibility software, programmatically, and so on. Therefore, to provide a comprehensive test for the feature, a suite of tests should include a set of tests interacting with the feature via the mouse (typing text just like a user might); one set interacting with the feature via keyboard, one set interacting with the feature via digitizer, one set interacting with the feature via accessibility software to invoke default actions and otherwise mimic an accessibility application, one set interacting with the feature via the application's coding model, and so on. It would be helpful if there were a way to make sure that the suite of test cases produced provided a comprehensive test of the feature or application and further, to decrease the total number of test cases that must be written to provide that comprehensive test.
Furthermore, much or all of the logic in each of these sets of test is identical to the logic in the other sets of tests and typically, much or all of the verification of results processing is identical as well. Hence, many tests are identical or very nearly so, merely varying execution options. For example, for all the multiple forms of input described above, the expected results are likely identical. Hence, writing a test case for each of these input sources typically requires writing a separate method for executing the test for each of the input sources, and duplicating most of the rest of the test script. Writing the same test over and over again with minor variations is tedious and time-consuming. It would be helpful if there were a way to eliminate or significantly reduce this duplicative coding and to reduce the total number of test cases that must be written.
Code written to determine if the actual results of running the test case coincide with the expected results (called verification of results, or verification) is often included within the test case. Changing the details of a particular result verification or adding new result verification typically requires the modification of each test case. It would be helpful if verification code were separate from the test case, making the test case easier to understand, and the verification code easier to reuse and to maintain.
Execution details are often hard-coded into the test case, requiring the design phase to be complete before the test case is written. It would be helpful if there were a way to define test cases in terms of user actions rather than in terms of specific execution details so that test cases could be written earlier in the software development life cycle.
Changes made to execution details and verification after the test cases are written typically requires a massive maintenance effort in which many test cases must be found and modified. It would be helpful if maintenance efforts could be localized so that modifications could be made in one place instead of in each test case.